#include "info.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


char recv_buffer[buffer_size];

char method[50];
char path[200];
char version[50];

char status[3];
char dsrp[100];
char type[20];
char length[20];
char file_path[200];
char* space="\r\n";

void run(int connfd){
    bzero(method,sizeof(method));
    bzero(path,sizeof(path));
    bzero(version,sizeof(version));
    bzero(status,sizeof(status));
    bzero(type,sizeof(type));
    bzero(dsrp,sizeof(dsrp));
    bzero(length,sizeof(length));


    strcpy(file_path,file_root);


    int n,i;
    bzero(recv_buffer,sizeof(recv_buffer));
        n=recv(connfd,recv_buffer,sizeof(recv_buffer),0);
        if(n<0)
            printf("Error: reading from socket\n");
        for(i=0;i<n;i++){
            printf("%c",recv_buffer[i]);
        }
        
        analyze();
        determinStatus();
        BindingPage();

        //char*resp= response(analyze(buffer),&size);
//        printf("%s",resp);
/*
        while(size>0){
            n=write(connfd,resp,size);
            size-=n;
        }
*/
        char resp_buffer[buffer_size];
       FILE* fp = fopen(file_path,"rb");
        fseek(fp,0,SEEK_END);
        long len=ftell(fp);
        fseek(fp,0,SEEK_SET);
        itoa(len,length);


        //Write the header
        char header[50];
        strcpy(header,"HTTP/1.0 ");
        strcat(header,status);
        strcat(header," ");
        strcat(header,dsrp);
        strcat(header,space);
        

        char contentType[50]={"Content-Type: "};
        strcat(contentType,type);
        strcat(contentType,space);
        

        char contentLength[50]={"Content-Length: "};
        strcat(contentLength,length);
        strcat(contentLength,space);

/*

        write(connfd,header,strlen(header));

        write(connfd,contentType,strlen(contentType));

        write(connfd,contentLength,strlen(contentLength));

        write(connfd,"\r\n\r\n",strlen("\r\n\r\n"));
*/

        char all_header[strlen(header)+strlen(contentType)+strlen(contentLength)+strlen("\r\n")];
        strcpy(all_header,header);
        strcat(all_header,contentType);
        strcat(all_header,contentLength);
        strcat(all_header,"\r\n");

        write(connfd,all_header,strlen(all_header));

        while(!feof(fp)){
                bzero(resp_buffer,sizeof(resp_buffer));
                fread(resp_buffer,sizeof(char),buffer_size,fp);
                write(connfd,resp_buffer,buffer_size);
        }
        fclose(fp);
        //free(resp);
        if (n<0)
            printf("Error: writing to socket\n");
        close(connfd);

}

void analyze()
{
    char* p=recv_buffer;
    char* header=NULL;
    struct rentry r;

    int i;

    //Copy method
    for(i=0;*p!='\r';i++){
        if(*(p+i)==' ')
        {
            strncpy(method,p,i);
            p=p+i+1;
            break;
        }
    }

    //Copy path
    for(i=0;*p!='\r';i++){
        if(*(p+i)==' ')
        {
            strncpy(path,p,i);
            p=p+i+1;
            break;
        }
    }

    //Copy verion
    for(i=0;;i++){
        if(*(p+i)=='\r')
        {
            strncpy(version,p,i);
            p+=i;
            break;
        }
    }

    //Type
    if (!strcmp(path,"/")){
        //Use the default page
        strcat(path,index_page);
        strcpy(type,".html");
        return;
    }

        char *p_type=strrchr(path,'.');
        if (!p_type)
        {
            strcpy(status,"401");
            strcpy(dsrp,"Bad Request: Invalid URI:");
            strcat(dsrp,path);
            return;

        }
        else{
            strcpy(type,p_type);

        }

    

}

void determinStatus()
{
    if (strcmp(method,"GET"))
    {
        strcpy(status,"401");
        strcpy(dsrp,"Bad Request: Invalid Method:");
        strcat(dsrp,method);

        return;
    }
    else if (strcmp(version,"HTTP/1.0") && strcmp(version,"HTTP/1.1"))
    {
        strcpy(status,"401");
        strcpy(dsrp,"Bad Request: Invalid HTTP-Version:");
        strcat(dsrp,version);

        return;
    }
    else if (strpbrk(path," <>#%"))
    {
        strcpy(status,"401");
        strcpy(dsrp,"Bad Request: Invalid URI:");
        strcat(dsrp,path);

        return;
    }
    if(!IsTypeSupported(type))
    {
        strcpy(status,"501");
        strcpy(dsrp," Not Implemented:");
        strcat(dsrp,path);
        return;
    }

    //Determine 404
    char* p_path=path;
    p_path++;
    char temp[50];
    strcpy(temp,file_root);
    strcat(temp,p_path);

    FILE* fp = fopen(temp,"rb");
    if (!fp)
    {
        strcpy(status,"404");
        strcpy(dsrp,"Not Found:");
        strcpy(dsrp,path);
        return;
    }

    strcat(file_path,p_path);
    fclose(fp);

    //Now is the 200
    strcpy(status,"200");
    strcpy(dsrp,"OK");
    return;
    
}

void BindingPage()
{
    if (strcmp(status,"200"))
    {
        strcpy(type,"text/html");
        strcat(file_path,status);
        strcat(file_path,".html");
    }
}

int IsTypeSupported(char* type)
{
    //convert the type html to text/html
    int i=0;
    for (i=0;i<20;i++){
        if (!strcmp(supportTypes[i],type))
        {
            strcpy(type,supportTypes[i+1]);
            return 1;
        }
    }
    return 0;
}